# Chapter 4: BASIC Programming ## Table of BASIC statements and functions | Keyword | Type | Summary | Origin | |-|-|-|-| | `ABS` | function | Returns absolute value of a number | C64 | | `AND` | operator | Returns boolean "AND" or bitwise intersection | C64 | | [`ASC`](#asc) | function | Returns numeric PETSCII value from string | C64 | | `ATN` | function | Returns arctangent of a number | C64 | | [`BANK`](#bank) | command | Sets the RAM and ROM banks to use for PEEK, POKE, and SYS | C128 | | [`BASLOAD`](#bank) | command | Load and tokenize a BASLOAD (.basl) text file | X16 | | [`BIN$`](#bin) | function | Converts numeric to a binary string | X16 | | [`BINPUT#`](#binput) | command | Reads a fixed-length block of data from an open file | X16 | | [`BLOAD`](#bload) | command | Loads a headerless binary file from disk to a memory address | X16 | | [`BOOT`](#boot) | command | Loads and runs `AUTOBOOT.X16` | X16 | | [`BSAVE`](#bsave) | command | Saves a headerless copy of a range of memory to a file | X16 | | `BVERIFY` | command | Verifies that a file on disk matches RAM contents | X16 | | [`BVLOAD`](#bvload) | command | Loads a headerless binary file from disk to VRAM | X16 | | [`CHAR`](#char) | command | Draws a text string in graphics mode | X16 | | `CHR$` | function | Returns PETSCII character from numeric value | C64 | | [`CLOSE`](#close) | command | Closes a logical file number | C64 | | `CLR` | command | Clears BASIC variable state | C64 | | [`CLS`](#cls) | command | Clears the screen | X16 | | `CMD` | command | Redirects output to non-screen device | C64 | | `CONT` | command | Resumes execution of a BASIC program | C64 | | [`COLOR`](#color) | command | Sets text fg and bg color | X16 | | `COS` | function | Returns cosine of an angle in radians | C64 | | `DA$` | variable | Returns the date in YYYYMMDD format from the system clock | X16 | | `DATA` | command | Declares one or more constants | C64 | | `DEF` | command | Defines a function for use later in BASIC | C64 | | `DIM` | command | Allocates storage for an array | C64 | | [`DOS`](#dos) | command | Disk and SD card directory operations | X16 | | [`EDIT`](#edit) | command | Open the built-in text editor | X16 | | `END` | command | Terminate program execution and return to `READY.` | C64 | | [`EXEC`](#exec) | command | Play back a script from RAM into the BASIC editor | X16 | | `EXP` | function | Returns the inverse natural log of a number | C64 | | [`FMCHORD`](#fmchord) | command | Start or stop simultaneous notes on YM2151 | X16 | | [`FMDRUM`](#fmdrum) | command | Plays a drum sound on YM2151 | X16 | | [`FMFREQ`](#fmfreq) | command | Plays a frequency in Hz on YM2151 | X16 | | [`FMINIT`](#fminit) | command | Stops sound and reinitializes YM2151 | X16 | | [`FMINST`](#fminst) | command | Loads a patch preset into a YM2151 channel | X16 | | [`FMNOTE`](#fmnote) | command | Plays a musical note on YM2151 | X16 | | [`FMPAN`](#fmpan) | command | Sets stereo panning on YM2151 | X16 | | [`FMPLAY`](#fmplay) | command | Plays a series of notes on YM2151 | X16 | | [`FMPOKE`](#fmpoke) | command | Writes a value into a YM2151 register | X16 | | [`FMVIB`](#fmvib) | command | Controls vibrato and tremolo on YM2151 | X16 | | [`FMVOL`](#fmvol) | command | Sets channel volume on YM2151 | X16 | | `FN` | function | Calls a previously defined function | C64 | | `FOR` | command | Declares the start of a loop construct | C64 | | [`FRAME`](#frame) | command | Draws an unfilled rectangle in graphics mode | X16 | | `FRE` | function | Returns the number of unused BASIC bytes free | C64 | | `GET` | command | Polls the keyboard cache for a single keystroke | C64 | | `GET#` | command | Polls an open logical file for a single character | C64 | | `GOSUB` | command | Jumps to a BASIC subroutine | C64 | | `GOTO` | command | Branches immediately to a line number | C64 | | [`HELP`](#help) | command | Displays a brief summary of online help resources | X16 | | [`HEX$`](#hex) | function | Converts numeric to a hexadecimal string | X16 | | [`I2CPEEK`](#i2cpeek) | function | Reads a byte from a device on the I²C bus | X16 | | [`I2CPOKE`](#i2cpoke) | command | Writes a byte to a device on the I²C bus | X16 | | `IF` | command | Tests a boolean condition and branches on result | C64 | | `INPUT` | command | Reads a line or values from the keyboard | C64 | | `INPUT#` | command | Reads lines or values from a logical file | C64 | | `INT` | function | Discards the fractional part of a number | C64 | | [`JOY`](#joy) | function | Reads gamepad button state | X16 | | [`KEYMAP`](#keymap) | command | Changes the keyboard layout | X16 | | `LEFT$` | function | Returns a substring starting from the beginning of a string | C64 | | `LEN` | function | Returns the length of a string | C64 | | `LET` | command | Explicitly declares a variable | C64 | | [`LINE`](#line) | command | Draws a line in graphics mode | X16 | | [`LINPUT`](#linput) | command | Reads a line from the keyboard | X16 | | [`LINPUT#`](#linput-1) | command | Reads a line or other delimited data from an open file | X16 | | [`LIST`](#list) | command | Outputs the program listing to the screen | C64 | | `LOAD` | command | Loads a program from disk into memory | C64 | | [`LOCATE`](#locate) | command | Moves the text cursor to new location | X16 | | `LOG` | function | Returns the natural logarithm of a number | C64 | | [`MENU`](#menu) | command | Invokes the Commander X16 utility menu | X16 | | `MID$` | function | Returns a substring from the middle of a string | C64 | | [`MON`](#mon) | command | Enters the machine language monitor | X16 | | [`MOUSE`](#mouse) | command | Hides or shows mouse pointer | X16 | | [`MOVSPR`](#movspr) | command | Set the X/Y position of a sprite | X16 | | [`MX/MY/MB`](#mxmymb) | variable | Reads the mouse position and button state | X16 | | [`MWHEEL`](#mwheel) | variable | Reads the mouse wheel movement | X16 | | `NEW` | command | Resets the state of BASIC and clears program memory | C64 | | `NEXT` | command | Declares the end of a loop construct | C64 | | `NOT` | operator | Bitwise or boolean inverse | C64 | | [`OLD`](#old) | command | Undoes a NEW command or warm reset | X16 | | `ON` | command | A GOTO/GOSUB table based on a variable value | C64 | | `OPEN` | command | Opens a logical file to disk or other device | C64 | | `OR` | operator | Bitwise or boolean "OR" | C64 | | [`OVAL`](#oval) | command | Draws a filled oval in graphics mode | X16 | | [`PEEK`](#peek) | function | Returns a value from a memory address | C64 | | `π` | function | Returns the constant for the value of pi | C64 | | [`POINTER`](#pointer) | function | Returns the address of a BASIC variable | C128 | | [`POKE`](#poke) | command | Assigns a value to a memory address | C64 | | `POS` | function | Returns the column position of the text cursor | C64 | | [`POWEROFF`](#poweroff) | command | Immediately powers down the Commander X16 | X16 | | `PRINT` | command | Prints data to the screen or other output | C64 | | `PRINT#` | command | Prints data to an open logical file | C64 | | [`PSET`](#pset) | command | Changes a pixel's color in graphics mode | X16 | | [`PSGCHORD`](#psgchord) | command | Starts or stops simultaneous notes on VERA PSG | X16 | | [`PSGFREQ`](#psgfreq) | command | Plays a frequency in Hz on VERA PSG | X16 | | [`PSGINIT`](#psginit) | command | Stops sound and reinitializes VERA PSG | X16 | | [`PSGNOTE`](#psgnote) | command | Plays a musical note on VERA PSG | X16 | | [`PSGPAN`](#psgpan) | command | Sets stereo panning on VERA PSG | X16 | | [`PSGPLAY`](#psgplay) | command | Plays a series of notes on VERA PSG | X16 | | [`PSGVOL`](#psgvol) | command | Sets voice volume on VERA PSG | X16 | | [`PSGWAV`](#psgwav) | command | Sets waveform on VERA PSG | X16 | | `READ` | command | Assigns the next `DATA` constant to one or more variables | C64 | | [`REBOOT`](#reboot) | command | Performs a warm reboot of the system | X16 | | [`RECT`](#rect) | command | Draws a filled rectangle in graphics mode | X16 | | `REM` | command | Declares a comment | C64 | | [`REN`](#ren) | command | Renumbers a BASIC program | X16 | | [`RESET`](#reset) | command | Performs a hard reset of the system | X16 | | [`RESTORE`](#restore) | command | Resets the `READ` pointer to a `DATA` constant | C64 | | `RETURN` | command | Returns from a subroutine to the statement following a GOSUB | C64 | | `RIGHT$` | function | Returns a substring from the end of a string | C64 | | [`RING`](#ring) | command | Draws an oval outline in graphics mode | X16 | | `RND` | function | Returns a floating point number 0 <= n < 1 | C64 | | [`RPT$`](#rpt) | function | Returns a string of repeated characters | X16 | | `RUN` | command | Clears the variable state and starts a BASIC program | C64 | | [`SAVE`](#save) | command | Saves a BASIC program from memory to disk | C64 | | [`SCREEN`](#screen) | command | Selects a text or graphics mode | X16 | | `SGN` | function | Returns the sign of a numeric value | C64 | | `SIN` | function | Returns the sine of an angle in radians | C64 | | [`SLEEP`](#sleep) | command | Introduces a delay in program execution | X16 | | `SPC` | function | Returns a string with a set number of spaces | C64 | | [`SPRITE`](#sprite) | command | Sets attributes for a sprite including visibility | X16 | | [`SPRMEM`](#sprmem) | command | Set the VRAM address for a sprite's visual data | X16 | | `SQR` | function | Returns the square root of a numeric value | C64 | | `ST` | variable | Returns the status of certain DOS/peripheral operations | C64 | | `STEP` | keyword | Used in a `FOR` declaration to declare the iterator step | C64 | | `STOP` | command | Breaks out of a BASIC program | C64 | | `STR$` | function | Converts a numeric value to a string | C64 | | [`STRPTR`](#strptr) | function | Returns the address of a BASIC string | X16 | | [`SYS`](#sys) | command | Transfers control to machine language at a memory address | C64 | | `TAB` | function | Returns a string with spaces used for column alignment | C64 | | `TAN` | function | Return the tangent for an angle in radians | C64 | | [`TATTR`](#tattr) | function | Returns a tile attribute from the tile/text layer | X16 | | [`TDATA`](#tdata) | function | Returns a tile from the tile/text layer | X16 | | `THEN` | keyword | Control structure as part of an `IF` statement | C64 | | `TI` | variable | Returns the jiffy timer value | C64 | | `TI$` | variable | Returns the time HHMMSS from the system clock | C64 | | [`TILE`](#tile) | command | Changes a tile or character on the tile/text layer | X16 | | `TO` | keyword | Part of the `FOR` loop declaration syntax | C64 | | `USR` | function | Call a user-defined function in machine language | C64 | | `VAL` | function | Parse a string to return a numeric value | C64 | | `VERIFY` | command | Verify that a BASIC program was written to disk correctly | C64 | | [`VPEEK`](#vpeek) | function | Returns a value from VERA's VRAM | X16 | | [`VPOKE`](#vpoke) | command | Sets a value in VERA's VRAM | X16 | | [`VLOAD`](#vload) | command | Loads a file to VERA's VRAM | X16 | | `WAIT` | command | Waits for a memory location to match a condition | C64 | ## Commodore 64 Compatibility The Commander X16 BASIC interpreter is 100% backwards-compatible with the Commodore 64 one. This includes the following features: * All statements and functions * Strings, arrays, integers, floats * Max. 80 character BASIC lines * Printing control characters like cursor control and color codes, e.g.: * `CHR$(147)`: clear screen * `CHR$(5)`: white text * `CHR$(18)`: reverse * `CHR$(14)`: switch to upper/lowercase font * `CHR$(142)`: switch to uppercase/graphics font * The BASIC vector table ($0300-$030B, $0311/$0312) * [SYS](#sys) arguments in RAM Because of the differences in hardware, the following functions and statements are incompatible between C64 and X16 BASIC programs. * `POKE`: write to a memory address * `PEEK`: read from a memory address * `WAIT`: wait for memory contents * `SYS`: execute machine language code (when used with ROM code) The BASIC interpreter also currently shares all problems of the C64 version, like the slow garbage collector. ## Saving Files By default, you cannot automatically overwrite a file with SAVE, BSAVE, or OPEN. To overwrite a file, you must prefix the filename with `@:`, like this: `SAVE "@:HELLO WORLD"`. (`"@0:filename"` is also acceptable.) This follows the Commodore convention, which extended to all of their diskette drives and third party hard drives and flash drive readers. Always confirm you have successfully saved a file by checking the DOS status. When you use the SAVE command from Immediate (or Direct) mode, the system does this for you. In Program mode, you have to do it yourself. There are two ways to check the error channel from inside a program: 1. You can use the DOS command and make the user perform actions necessary to recover from an error (such as re-saving the file with an @: prefix). 2. You can read the error yourself, using the following BASIC code: ```BASIC 10 OPEN 15,8,15 20 INPUT#15,A,B$ 30 PRINT A;B$ 40 CLOSE 15 ``` Refer to [Chapter 13](X16%20Reference%20-%2013%20-%20Working%20with%20CMDR-DOS.md#chapter-13-working-with-cmdr-dos) for more details on CMDR-DOS and the command channel. ## New Statements and Functions There are several new statement and functions. Note that all BASIC keywords (such as `FOR`) get converted into tokens (such as `$81`), and the tokens for the new keywords have likely shifted from one ROM version to the next. Therefore, loading BASIC program saved from an old revision of BASIC may mix up keywords. As of ROM version R42, the keyword token positions should no longer shift and programs saved in R42 BASIC should be compatible with future versions. ### ASC **TYPE: Integer Function** **FORMAT: ASC(<string>)** **Action:** Returns an integer value representing the PETSCII code for the first character of `string`. If `string` is the empty string, `ASC()` returns 0. **EXAMPLE of ASC Function:** ```BASIC ?ASC("A") 65 ?ASC("") 0 ``` ### BIN$ **TYPE: String Function** **FORMAT: BIN$(n)** **Action:** Return a string representing the binary value of n. If n <= 255, 8 characters are returned and if 255 < n <= 65535, 16 characters are returned. **EXAMPLE of BIN$ Function:** ```BASIC PRINT BIN$(200) : REM PRINTS 11001000 AS BINARY REPRESENTATION OF 200 PRINT BIN$(45231) : REM PRINTS 1011000010101111 TO REPRESENT 16 BITS ``` ### BANK **TYPE: Command** **FORMAT: BANK m[,n]** **Action:** Set the active RAM (m) and ROM bank (n) for the purposes of `PEEK`, `POKE`, and `SYS`. Specifying the ROM bank is optional. If it is not specified, its previous value is retained. **EXAMPLE of BANK Statement:** ```BASIC BANK 1,10 : REM SETS THE RAM BANK TO 1 AND THE ROM BANK TO 10 ?PEEK($A000) : REM PRINTS OUT THE VALUE STORED IN $A000 IN RAM BANK 1 SYS $C063 : REM CALLS ROUTINE AT $C09F IN ROM BANK 10 AUDIO (YM_INIT) ``` Note: In the above example, the `SYS $C063` in ROM bank 10 is a call to [ym_init](X16%20Reference%20-%2011%20-%20Sound%20Programming.md#audio-api-routines), which does the first half of what the BASIC command `FMINIT` does, without setting any default instruments. It is generally not recommended to call routines in ROM directly this way, and most BASIC programmers will never have a need to call `SYS` directly, but advanced users may find a good reason to do so. Note: BANK uses its own register to store the the command's desired bank numbers; this will not always be the same as the value stored in `$00` or `$01`. In fact, `$01` is always going to read `4` when PEEKing from BASIC. If you need to know the currently selected RAM and/or RAM banks, you should explicitly set them and use variables to track your selected bank number(s). Note: Memory address `$00`, which is the hardware RAM bank register, will usually report the bank set by the `BANK` command. The one exception is after a `BLOAD` or `BVERIFY` inside of a running BASIC program. `BLOAD` and `BVERIFY` change the RAM bank (as if you called `BANK`) to the bank that `BLOAD` or `BVERIFY` stopped at. ### BASLOAD **TYPE: Command** **FORMAT: BASLOAD <filename>** **Action:** Loads a plain text file with BASLOAD source and converts it into a runnable program. For more information about BASLOAD, see [this external documentation](https://github.com/stefan-b-jakobsson/basload-rom) **EXAMPLE of BASLOAD Command:** ```BASIC BASLOAD "MYPROG.BASL" LOADING... READY. LIST 1 PRINT "HELLO, WORLD!" 2 GOTO 1 READY. ``` ### BINPUT# **TYPE: Command** **FORMAT: BINPUT# <n>,<var$>,<len>** **Action:** `BINPUT#` Reads a block of data from an open file and stores the data into a string variable. If there are fewer than `` bytes available to be read from the file, fewer bytes will be stored. If the end of the file is reached, `ST AND 64` will be true. **EXAMPLE of BINPUT# Statement:** ```BASIC 10 OPEN 8,8,8,"FILE.BIN,S,R" 20 BINPUT#8,A$,10 30 PRINT "I GOT";LEN(A$);"BYTES" 40 IF ST<>0 THEN 20 50 CLOSE 8 ``` ### BOOT **TYPE: Command** **FORMAT: BOOT** **Action:** Load and run a PRG file named `AUTOBOOT.X16` from device 8. If the file is not found, nothing is done and no error is printed. **EXAMPLE of BOOT Statement:** ```BASIC BOOT ``` ### BLOAD **TYPE: Command** **FORMAT: BLOAD <filename>, <device>, <bank>, <address>** **Action:** Loads a binary file directly into RAM Note: If the file is loaded to high RAM (starting in the range `$A000-$BFFF`), and the file is larger than what would fit in the current bank, the load will wrap around into subsequent banks. After a successful load, `$030D` and `$030E` will contain the address of the final byte loaded + 1. If relevant, the value in memory location `$00` will point to the bank in which the next byte would have been loaded. **EXAMPLES of BLOAD:** ```BASIC BLOAD "MYFILE.BIN",8,1,$A000:REM LOADS A FILE NAMED MYFILE.BIN FROM DEVICE 8 STARTING IN BANK 1 AT $A000. BLOAD "WHO.PCX",8,10,$B000:REM LOADS A FILE NAMED WHO.PCX INTO RAM STARTING IN BANK 10 AT $B000. ``` ### BSAVE **TYPE: Command** **FORMAT: BSAVE <filename>, <device>, <bank>, <start address>, <end address>** **Action:** Saves a region of memory to a binary file. Note: The save will stop one byte before `end address`. This command does not allow for automatic bank advancing, but you can achieve a similar result with successive BSAVE invocations to append additional memory locations to the same file. **EXAMPLES of BSAVE:** ```BASIC BSAVE "MYFILE.BIN",8,1,$A000,$C000 ``` The above example saves a region of memory from \$A000 in bank 1 through and including \$BFFF, stopping before \$C000. ```BASIC BSAVE "MYFILE.BIN,S,A",8,2,$A000,$B000 ``` The above example appends a region of memory from \$A000 through and including \$AFFF, stopping before \$B000. Running both of the above examples in succession will result in a file MYFILE.BIN 12KiB in size. **Warning:** Appending to file involves a risk of corrupting the file system of the SD card! See [Appending to file](X16%20Reference%20-%2013%20-%20Working%20with%20CMDR-DOS.md#appending-to-file). ### BVLOAD **TYPE: Command** **FORMAT: BVLOAD <filename>, <device>, <VERA_high_address>, <VERA_low_address>** **Action:** Loads a binary file directly into VERA RAM. **EXAMPLES of BVLOAD:** ```BASIC BVLOAD "MYFILE.BIN", 8, 0, $4000 :REM LOADS MYFILE.BIN FROM DEVICE 8 TO VRAM $4000. BVLOAD "MYFONT.BIN", 8, 1, $F000 :REM LOAD A FONT INTO THE DEFAULT FONT LOCATION ($1F000). ``` ### CHAR **TYPE: Command** **FORMAT: CHAR <x>,<y>,<color>,<string>** **Action:** This command draws a text string on the graphics screen in a given color. The string can contain printable ASCII characters (`CHR$($20)` to `CHR$($7E)`), as well most PETSCII control codes. **EXAMPLE of CHAR Statement:** ```BASIC 10 SCREEN $80 20 A$="The quick brown fox jumps over the lazy dog." 24 CHAR 0,6,0,A$ 30 CHAR 0,6+12,0,CHR$($04)+A$ :REM UNDERLINE 40 CHAR 0,6+12*2,0,CHR$($06)+A$ :REM BOLD 50 CHAR 0,6+12*3,0,CHR$($0B)+A$ :REM ITALICS 60 CHAR 0,6+12*4,0,CHR$($0C)+A$ :REM OUTLINE 70 CHAR 0,6+12*5,0,CHR$($12)+A$ :REM REVERSE ``` ### CLOSE **TYPE: Command** **FORMAT: CLOSE <file number>** **Action:** Closes any files used by `OPEN` statements. The `CLOSE` statement takes a single argument that is the file number to be closed. **EXAMPLE of CLOSE Statement:** ```BASIC CLOSE 0 : REM CLOSE FILE OPENED AS 0 CLOSE 4 : REM CLOSE FILE OPENED AS 4 ``` ### CLS **TYPE: Command** **FORMAT: CLS** **Action:** Clears the screen. Same effect as `?CHR$(147);`. **EXAMPLE of CLS Statement:** ```BASIC CLS ``` ### COLOR **TYPE: Command** **FORMAT: COLOR <fgcol>[,<bgcol>]** **Action:** This command works sets the text mode foreground color, and optionally the background color. **EXAMPLES of COLOR Statement:** ```BASIC COLOR 2 : REM SET FG COLOR TO RED, KEEP BG COLOR COLOR 2,0 : REM SET FG COLOR TO RED, BG COLOR TO BLACK ``` ### DOS **TYPE: Command** **FORMAT: DOS <string>** **Action:** This command works with the command/status channel or the directory of a Commodore DOS device and has different functionality depending on the type of argument. * Without an argument, `DOS` prints the status string of the current device. * With a string argument of `"8"` or `"9"`, it switches the current device to the given number. * With an argument starting with `"$"`, it shows the directory of the device. * Any other argument will be sent as a DOS command. **EXAMPLES of DOS Statement:** ```BASIC DOS"$" : REM SHOWS DIRECTORY DOS"S:BAD_FILE" : REM DELETES "BAD_FILE" DOS : REM PRINTS DOS STATUS, E.G. "01,FILES SCRATCHED,01,00" ``` ### EDIT **TYPE: Command** **FORMAT: EDIT \[<filename>\]** **Action:** Opens the built-in text editor, X16-Edit, a modeless editor with features similar to GNU Nano. * Without an argument, the editor begins with an empty file. * With a string argument, it attempts to load a file before displaying it. The EDIT command loads the editor in the screen mode and character set that was active at the time the command was run. **EXAMPLE of EDIT Statement:** ```BASIC EDIT "README.TXT" ``` A more elaborate X16-Edit manual can be found [here](https://github.com/X16Community/x16-rom/blob/master/x16-edit/docs/manual.pdf) ### EXEC **TYPE: Command** **FORMAT: EXEC <memory address>\[,<ram bank>\]** **Action:** Plays back a null-terminated script from MEMORY into the BASIC editor. Among other uses, this can be used to "type" in a program from a plain text file. * If the `ram bank` argument is omitted and the address is in the range \$A000-\$BFFF, the RAM bank selected by the `BANK` command is used. * The input can span multiple RAM banks. The input will stop once it reaches a null byte ($00) or if a BASIC error occurs. * The redirected input only applies to BASIC immediate mode. While programs are running, the EXEC handling is suspended. **EXAMPLE of EXEC Statement:** ```BASIC BLOAD "MYPROGRAM.BAS",8,1,$A000 : REM "BANK PEEK(0)" NO LONGER NEEDED POKE PEEK($30D)+(PEEK($30E)*256),0 : REM NULL TERMINATE IN END BANK EXEC $A000,1 ``` This program will load a plain ASCII or PETSCII FILE.BAS from disk and tokenize it for you: ```BASIC 10 BLOAD "FILE.BAS", 8, 1, $A000 20 POKE PEEK(781) + 256 * PEEK(782), 0 30 EXEC $A000, 1 40 NEW ``` ### FMCHORD **TYPE: Command** **FORMAT: FMCHORD <first channel>,<string>** **Action:** This command uses the same syntax as `FMPLAY`, but instead of playing a series of notes, it will start all of the notes in the string simultaneously on one or more channels. The first parameter to `FMCHORD` is the first channel to use, and will be used for the first note in the string, and subsequent notes in the string will be started on subsequent channels, with the channel after 7 being channel 0. All macros are supported, even the ones that only affect the behavior of `PSGPLAY` and `FMPLAY`. The full set of macros is documented [here](X16%20Reference%20-%20Appendix%20A%20-%20Sound.md#basic-fmplay-and-psgplay-string-macros). **EXAMPLE of FMCHORD statement:** ```BASIC 10 FMINIT 20 FMVIB 195,10 30 FMINST 1,16:FMINST 2,16:FMINST 3,16 : REM ORGAN 40 FMVOL 1,50:FMVOL 2,50:FMVOL 3,50 : REM MAKE ORGAN QUIETER 50 FMINST 0,11 : REM VIBRAPHONE 60 FMCHORD 1,"O3CG>E T90" : REM START SOME ORGAN CHORDS (CHANNELS 1,2,3) 70 FMPLAY 0,"O4G4.A8G4E2." : REM PLAY MELODY (CHANNEL 0) 80 FMPLAY 0,"O4G4.A8G4E2." 90 FMCHORD 1,"O2G>DB" : REM SWITCH ORGAN CHORDS (CHANNELS 1,2,3) 100 FMPLAY 0,"O5D2D4CRCCR" : REM FOURTH LINE ``` ### FMPOKE **TYPE: Command** **FORMAT: FMPOKE <register>,<value>** **Action:** This command uses the AUDIO API to write a value to one of the the YM2151's registers at a low level. **EXAMPLE of FMPOKE statement:** ```BASIC 10 FMINIT 20 FMPOKE $28,$4A : REM SET KC TO A4 (A-440) ON CHANNEL 0 30 FMPOKE $08,$00 : REM RELEASE CHANNEL 0 40 FMPOKE $08,$78 : REM START NOTE PLAYBACK ON CHANNEL 0 W/ ALL OPERATORS ``` ### FMVIB **TYPE: Command** **FORMAT: FMVIB <speed>,<depth>** **Action:** This command sets the LFO speed and the phase and amplitude modulation depth values on the YM2151. The speed value ranges from 0 to 255, and corresponds to an LFO frequency from 0.008 Hz to 32.6 Hz. The depth value ranges from 0-127 and affects both AMD and PMD. Only some patch presets (instruments) are sensitive to the LFO. Those are marked in [this table](X16%20Reference%20-%20Appendix%20A%20-%20Sound.md#fm-instrument-patch-presets) with the † symbol. The LFO affects all channels equally, and it depends on the instrument as to whether it is affected. Good values for most instruments are speed somewhere between 190-220. A good light vibrato for most wind instruments would have a depth of 10-15, while tremolo instruments like the Vibraphone or Tremolo Strings are most realistic around 20-30. **EXAMPLE of FMVIB statement:** ```BASIC 10 FMVIB 200,30 20 FMINST 0,11 : REM VIBRAPHONE 30 FMPLAY 0,"T60 O4 CDEFGAB>C" 40 FMVIB 0,0 50 FMPLAY 0,"C= 0 THEN J = I: GOTO40 30 NEXT 40 : 50 V=JOY(J) 60 PRINT CHR$(147);V;": "; 70 IF V = -1 THEN PRINT"DISCONNECTED ": GOTO50 80 IF V AND 8 THEN PRINT"UP "; 90 IF V AND 4 THEN PRINT"DOWN "; 100 IF V AND 2 THEN PRINT"LEFT "; 110 IF V AND 1 THEN PRINT"RIGHT "; 120 GOTO50 ``` ### KEYMAP **TYPE: Command** **FORMAT: KEYMAP <string>** **Action:** This command sets the current keyboard layout. It can be put into an AUTOBOOT file to always set the keyboard layout on boot. **EXAMPLE of KEYMAP Statement:** ```BASIC 10 KEYMAP"SV-SE" :REM SMALL BASIC PROGRAM TO SET LAYOUT TO SWEDISH/SWEDEN SAVE"AUTOBOOT.X16" :REM SAVE AS AUTOBOOT FILE ``` ### LINE **TYPE: Command** **FORMAT: LINE <x1>,<y1>,<x2>,<y2>,<color>** **Action:** This command draws a line on the graphics screen in a given color. **EXAMPLE of LINE Statement:** ```BASIC 10 SCREEN128 20 FORA=0TO2*πSTEP2*π/200 30 : LINE100,100,100+SIN(A)*100,100+COS(A)*100 40 NEXT ``` **If you're pasting this example into the Commander X16 emulator, use this code block instead so that the π symbol is properly received.** ```BASIC 10 SCREEN128 20 FORA=0TO2*\XFFSTEP2*\XFF/200 30 : LINE100,100,100+SIN(A)*100,100+COS(A)*100 40 NEXT ``` ### LINPUT **TYPE: Command** **FORMAT: LINPUT <var$> **Action:** `LINPUT` Reads a line of data from the keyboard and stores the data into a string variable. Unlike `INPUT`, no parsing or cooking of the input is done, and therefore quotes, commas, and colons are stored in the string as typed. No prompt is displayed, either. The input is taken from the KERNAL editor, hence the user will have the freedom of all of the features of the editor such as cursor movement, mode switching, and color changing. Due to how the editor works, an empty line will return `" "`– a string with a single space, and trailing spaces are not preserved. **EXAMPLE of LINPUT Statement:** ```BASIC 10 LINPUT A$ 20 IF A$=" " THEN 50 30 PRINT "YOU TYPED: ";A$ 40 END 50 PRINT "YOU TYPED AN EMPTY STRING: ";A$ ``` ### LINPUT# **TYPE: Command** **FORMAT: LINPUT# <n>,<var$>\[,<delimiter>\]** **Action:** `LINPUT#` Reads a line of data from an open file and stores the data into a string variable. The delimiter of a line by default is 13 (carriage return). The delimiter is not part of the stored value. If the end of the file is reached while reading, `ST AND 64` will be true. `LINPUT#` can be used to read structured data from files. It can be particularly useful to extract quoted or null-terminated strings from files while reading. **EXAMPLE of LINPUT# Statement:** ```BASIC 10 I=0 20 OPEN 1,8,0,"$" 30 LINPUT#1,A$,$22 40 IF ST<>0 THEN 130 50 LINPUT#1,A$,$22 60 IF I=0 THEN 90 70 PRINT "ENTRY: "; 80 GOTO 100 90 PRINT "LABEL: "; 100 PRINT CHR$($22);A$;CHR$($22) 110 I=I+1 120 IF ST=0 THEN 30 130 CLOSE 1 ``` The above example parses and prints out the filenames from a directory listing. ### LIST **TYPE: Command** **FORMAT: LIST [start] [-] [end]** **Action:** `LIST` Displays the currently loaded BASIC program on the screen. The start and ending line numbers are both optional. The start and/or end may be specified. If both are specified, a hyphen must be included. So LIST has 4 modes: `LIST` by itself will display the entire program. `LIST 10-20` will display lines 10 to 20, inclusive. `LIST -100` will display from the start to line 100 `LIST 50-` will display line 50 to the end of the program. Pressing the `CONTROL` key during a listing will slow the listing down once printing reaches the bottom of the screen. Approximately one line per second will be displayed. Pressing the `SPACE BAR` during the listing will cause the listing to pause. Pressing the `SPACE BAR` a second time will unpause the listing. You may also use the down arrow key to scroll by one line or use the `PgDn` key to scroll approximately one screen full of text. ### LOCATE **TYPE: Command** **FORMAT: LOCATE <line>[,<column>]** **Action:** This command positions the text mode cursor at the given location. The values are 1-based. If no column is given, only the line is changed. **EXAMPLE of LOCATE Statement:** ```BASIC 100 REM DRAW CIRCLE ON TEXT SCREEN 110 SCREEN0 120 R=25 130 X0=40 140 Y0=30 150 FORT=0TO360STEP1 160 : X=X0+R*COS(T) 170 : Y=Y0+R*SIN(T) 180 : LOCATEY,X:PRINTCHR$($12);" "; 190 NEXT ``` ### MENU **TYPE: Command** **FORMAT: MENU** **Action:** This command currently invokes the Commander X16 Control Panel. In the future, the menu may instead present a menu of ROM-based applications and routines. **EXAMPLE of MENU Statement:** ```BASIC MENU ``` ### MON **TYPE: Command** **FORMAT: MON (Alternative: MONITOR)** **Action:** This command enters the machine language monitor. See the [Chapter 7: Machine Language Monitor](X16%20Reference%20-%2007%20-%20Machine%20Language%20Monitor.md#chapter-7-machine-language-monitor) for a description. **EXAMPLE of MON Statement:** ```BASIC MON MONITOR ``` ### MOUSE **TYPE: Command** **FORMAT: MOUSE <mode>** **Action:** This command configures the mouse pointer. | Mode | Description | |------|------------------------------------------| | 0 | Hide mouse | | 1 | Show mouse, set default mouse pointer | | -1 | Show mouse, don't configure mouse cursor | `MOUSE 1` turns on the mouse pointer and `MOUSE 0` turns it off. If the BASIC program has its own mouse pointer sprite configured, it can use `MOUSE -1`, which will turn the mouse pointer on, but not set the default pointer sprite. The sprite attributes for the mouse pointer are always read from VERA address $1:FC00-$1:FC07, the attributes for sprite 0. The default cursor will be written to the default sprite 0 data address in VERA at $1:3000 when Mode is set to 1. The size of the mouse pointer's area will be configured according to the current screen mode. If the screen mode is changed, the MOUSE statement has to be repeated. **EXAMPLES of MOUSE Statement:** ```BASIC MOUSE 1 : REM ENABLE MOUSE MOUSE 0 : REM DISABLE MOUSE ``` ### MOVSPR **TYPE: Command** **FORMAT: MOVSPR <sprite idx>,<x>,<y>** **Action:** This command positions a sprite's upper left corner at a specific pixel location. It does not change its visibility. `sprite idx` is a value between 0-127 inclusive. `x` and `y` have a range of -32768 to 32767 inclusive, but their meanings wrap every 1024 values. Values approaching 1023 will peek out from the left and top of the screen for x and y respectively as if they were negative and approaching 0. -1024, 1024, 0, and 2048 are all equivalent. Likewise, -10 and 1014 are equivalent. **EXAMPLE of MOVSPR Statement:** ```BASIC 10 BVLOAD "MYSPRITE.BIN",8,1,$3000 20 SPRMEM 1,1,$3000,1 30 SPRITE 1,3,0,0,3,3 40 MOVSPR 1,320,200 ``` ### MX/MY/MB **TYPE: System variable** **FORMAT: MX** **FORMAT: MY** **FORMAT: MB** **Action:** Return the horizontal (`MX`) or vertical (`MY`) position of the mouse pointer, or the mouse button state (`MB`). `MB` returns the sum of the following values depending on the state of the buttons: | Value | Button | |-------|--------| | 0 | none | | 1 | left | | 2 | right | | 4 | third | **EXAMPLE of MX/MY/MB variables:** ```BASIC REM SIMPLE DRAWING PROGRAM 10 SCREEN$80 20 MOUSE1 25 OB=0 30 TX=MX:TY=MY:TB=MB 35 IFTB=0GOTO25 40 IFOBTHENLINEOX,OY,TX,TY,16 50 IFOB=0THENPSETTX,TY,16 60 OX=TX:OY=TY:OB=TB 70 GOTO30 ``` ### MWHEEL **TYPE: System variable** **FORMAT: MWHEEL** **Action:** Return the mouse scroll wheel movement since the value was last read. The value is negative if the scroll wheel is moved away from the user, and positive if it is moved towards the user. The range of the returned value is -128 to +127. ### OLD **TYPE: Command** **FORMAT: OLD** **Action:** This command recovers the BASIC program in RAM that has been previously deleted using the `NEW` command or through a RESET. **EXAMPLE of OLD Statement:** ```BASIC OLD ``` ### OVAL **TYPE: Command** **FORMAT: OVAL <x1>,<y1>,<x2>,<y2>,<color>** **Action:** This command draws a filled oval on the graphics screen in a given color. The coordinate arguments define the rectangular bounding box of the oval. To draw a filled circle, make the width and height equal to each other. **EXAMPLE of OVAL Statement:** ```BASIC 10 SCREEN $80 20 FORI=1 TO 20:OVAL RND(1)*320,RND(1)*200,RND(1)*320,RND(1)*200,RND(1)*128:NEXT 30 GOTO 20 ``` ### PEEK **TYPE: Command** **FORMAT: PEEK(<address>)** **Action:** Returns the value at given memory address PEEKing values within the BRAM (`$A000`) and KERNAL/Cartridge (`$C000`) requires using `BANK` to set the banks accordingly. **EXAMPLE of PEEK function:** ```BASIC 10 A=PEEK($C000) 20 PRINT A ``` ### POINTER **TYPE: Function** **FORMAT: POINTER(<variable>)** **Action:** Returns the memory address of the internal structure representing a BASIC variable. **EXAMPLE of POINTER function:** ```BASIC 10 A$="MOO" 20 PRINT HEX$(POINTER(A$)) RUN 0823 ``` ### POKE **TYPE: Function** **FORMAT: POKE <address>, <value>** **Action:** Sets the contents of the memory address to given value. To write to memory within a RAMBANK page, [`BANK`](#bank) must be called beforehand with the appropriate arguments. Writing to values within the KERNAL/Cartridge area (`$C000`) will not work as expected and may silently fail in KERNAL ROM versions older than R49. In R49, POKE works as expected assuming the area being written to is RAM and that [`BANK`](#bank) has been called with appropriate arguments. **EXAMPLE of POKE function:** ```BASIC 10 POKE $A000,47 ``` ### POWEROFF **TYPE: Command** **FORMAT: POWEROFF** **Action:** This command instructs the SMC to power down the system. This is equivalent to pressing the physical power switch. **EXAMPLE of POWEROFF Statement:** ```BASIC POWEROFF ``` ### PSET **TYPE: Command** **FORMAT: PSET <x>,<y>,<color>** **Action:** This command sets a pixel on the graphics screen to a given color. **EXAMPLE of PSET Statement:** ```BASIC 10 SCREEN$80 20 FORI=1TO20:PSETRND(1)*320,RND(1)*200,RND(1)*256:NEXT 30 GOTO20 ``` ### PSGCHORD **TYPE: Command** **FORMAT: PSGCHORD <first voice>,<string>** **Action:** This command uses the same syntax as `PSGPLAY`, but instead of playing a series of notes, it will start all of the notes in the string simultaneously on one or more voices. The first parameter to `PSGCHORD` is the first voice to use, and will be used for the first note in the string, and subsequent notes in the string will be started on subsequent voices, with the voice after 15 being voice 0. All macros are supported, even the ones that only affect `PSGPLAY` and `FMPLAY`. The full set of macros is documented [here](X16%20Reference%20-%20Appendix%20A%20-%20Sound.md#basic-fmplay-and-psgplay-string-macros). **EXAMPLE of PSGCHORD statement:** ```BASIC 10 PSGINIT 20 PSGCHORD 15,"O3G>CE" : REM STARTS PLAYING A CHORD ON VOICES 15, 0, AND 1 30 PSGPLAY 14,">CCDE" : REM PLAYS A SERIES OF NOTES ON VOICE 14 40 PSGCHORD 15,"RRR" : REM RELEASES CHORD ON VOICES 15, 0, AND 1 50 PSGPLAY 14,"O4CAG>CCF" : REM STARTS PLAYING A CHORD ON VOICES 0, 1, AND 2 70 PSGPLAY 14,"L16FGAB->CDEF4" : REM PLAYS A SERIES OF NOTES ON VOICE 80 PSGCHORD 0,"RRR" : REM RELEASES CHORD ON VOICES 0, 1, AND 2 ``` ### PSGFREQ **TYPE: Command** **FORMAT: PSGFREQ <voice>,<frequency>** **Action:** Play a note by frequency on the VERA PSG. The accepted range is in Hz from 1 to 24319. PSGFREQ also accepts a frequency of 0 to release the note. **EXAMPLE of PSGFREQ statement:** ```BASIC 10 PSGINIT : REM RESET ALL VOICES TO SQUARE WAVEFORM 20 PSGFREQ 0,350 : REM PLAY A SQUARE WAVE AT 350 HZ 30 PSGFREQ 1,440 : REM PLAY A SQUARE WAVE AT 440 HZ ON ANOTHER VOICE 40 FOR X=1 TO 10000 : NEXT X : REM DELAY A BIT 50 PSGFREQ 0,0 : PSGFREQ 1,0 : REM RELEASE BOTH VOICES ``` The above BASIC program plays a sound similar to a North American dial tone for a few seconds. ### PSGINIT **TYPE: Command** **FORMAT: PSGINIT** **Action:** Initialize VERA PSG, silence all voices, set volume to 63 on all voices, and set the waveform to pulse and the duty cycle to 63 (50%) for all 16 voices. ### PSGNOTE **TYPE: Command** **FORMAT: PSGNOTE <voice>,<note>** **Action:** Play a note on the VERA PSG. The note value is constructed as follows. Using hexadecimal notation, the first nybble is the octave, 0-7, and the second nybble is the note within the octave as follows: | `$x0` | `$x1` | `$x2` | `$x3` | `$x4` | `$x5` | `$x6` | `$x7` | `$x8` | `$x9` | `$xA` | `$xB` | `$xC` | `$xD-$xF` | |-|-|-|-|-|-|-|-|-|-|-|-|-|-| | Release | C | C♯/D♭ | D | D♯/E♭ | E | F | F♯/G♭ | G | G♯/A♭ | A | A♯/B♭ | B | no-op | **EXAMPLE of PSGNOTE statement:** ```BASIC 10 PSGNOTE 1,$4A : REM PLAYS CONCERT A 20 FOR X=1 TO 5000 : NEXT X : REM DELAYS FOR A BIT 30 PSGNOTE 1,0 : REM RELEASES THE NOTE 40 FOR X=1 TO 2500 : NEXT X : REM SHORT DELAY 50 PSGNOTE 1,$3A : REM PLAYS A IN THE 3RD OCTAVE 60 FOR X=1 TO 2500 : NEXT X : REM SHORT DELAY 70 PSGNOTE 1,0 : REM RELEASES THE NOTE ``` ### PSGPAN **TYPE: Command** **FORMAT: PSGPAN <voice>,<panning>** **Action:** Sets the simple stereo panning on a VERA PSG voice. Valid values are as follows: * 1 = left * 2 = right * 3 = both ### PSGPLAY **TYPE: Command** **FORMAT: PSGPLAY <voice>,<string>** **Action:** This command is very similar to `PLAY` on other BASICs such as GWBASIC. It takes a string of notes, rests, tempo changes, note lengths, and other macros, and plays all of the notes synchronously. That is, the PSGPLAY command will not return control until all of the notes and rests in the string have been fully played. The full set of macros is documented [here](X16%20Reference%20-%20Appendix%20A%20-%20Sound.md#basic-fmplay-and-psgplay-string-macros). **EXAMPLE of PSGPLAY statement:** ```BASIC 10 PSGWAV 0,31 : REM PULSE, 25% DUTY 20 PSGPLAY 0,"T180 S0 O5 L32" : REM TEMPO 180 BPM, LEGATO, OCTAVE 5, 32ND NOTES 30 PSGPLAY 0,"CCEG>CCE-A-E-A->CE-A-" 50 PSGPLAY 0,"E-<DFB-FB->DFB-F" : REM GRAB YOURSELF A MUSHROOM ``` ### PSGVOL **TYPE: Command** **FORMAT: PSGVOL <voice>,<volume>** **Action:** This command sets the voice's volume. The volume remains at the requested level until another `PSGVOL` command for that voice or `PSGINIT` is called. Valid range is from 0 (completely silent) to 63 (full volume). ### PSGWAV **TYPE: Command** **FORMAT: PSGWAV <voice>,<w>** **Action:** Sets the waveform and duty cycle for a PSG voice. * w = 0-63 -> Pulse: Duty cycle is `(w+1)/128`. A value of 63 means 50% duty. * w = 64-127 -> Sawtooth (all values have identical effect) * w = 128-191 -> Triangle (all values have identical effect) * w = 192-255 -> Noise (all values have identical effect) **EXAMPLE of PSGWAV Statement:** ```BASIC 10 FOR O=$20 TO $50 STEP $10:REM OCTAVE LOOP 20 FOR N=1 TO 11 STEP 2:REM NOTE LOOP, EVERY OTHER NOTE 30 PSGNOTE 0,O+N:REM START PLAYBACK OF THE NOTE 40 FOR P=0 TO 30:REM PULSE WIDTH MODULATION LOOP (INCREASING DUTY) 50 PSGWAV 0,P:REM SET PW 60 FOR D=1 TO 30:NEXT D:REM DELAY LOOP 70 NEXT P 80 PSGNOTE 0,O+N+1:REM START PLAYBACK OF THE NOTE + A SEMITONE 90 FOR P=31 TO 1 STEP -1:REM PWM LOOP (DECREASING DUTY) 100 PSGWAV 0,P:REM SET PW 110 FOR D=1 TO 30:NEXT D:REM DELAY LOOP 120 NEXT P 130 NEXT N 140 NEXT O 150 PSGNOTE 0,0:REM STOP SOUND ``` This example plays a chromatic scale while applying pulse-width modulation on the voice. ### RING **TYPE: Command** **FORMAT: RING <x1>,<y1>,<x2>,<y2>,<color>** **Action:** This command draws an oval outline on the graphics screen in a given color. The coordinate arguments define the rectangular bounding box of the oval. To draw a circle outline, make the width and height equal to each other. **EXAMPLE of RING Statement:** ```BASIC 10 SCREEN $80 20 FORI=1 TO 20:RING RND(1)*320,RND(1)*200,RND(1)*320,RND(1)*200,RND(1)*128:NEXT 30 GOTO 20 ``` ### RECT **TYPE: Command** **FORMAT: RECT <x1>,<y1>,<x2>,<y2>,<color>** **Action:** This command draws a solid rectangle on the graphics screen in a given color. **EXAMPLE of RECT Statement:** ```BASIC 10 SCREEN$80 20 FORI=1TO20:RECTRND(1)*320,RND(1)*200,RND(1)*320,RND(1)*200,RND(1)*256:NEXT 30 GOTO20 ``` ### REBOOT **TYPE: Command** **FORMAT: REBOOT** **Action:** Performs a software reset of the system by calling the ROM reset vector. **EXAMPLE of REBOOT Statement:** ```BASIC REBOOT ``` ### REN **TYPE: Command** **FORMAT: REN [<new line num>[, <increment>[, <first old line num>]]]** **Action:** Renumbers a BASIC program while updating the line number arguments of GOSUB, GOTO, RESTORE, RUN, and THEN. Optional arguments: * The line number of the first line after renumbering, default: **10** * The value of the increment for subsequent lines, default **10** * The earliest old line to start renumbering at, default: **0** **THIS STATEMENT IS EXPERIMENTAL**. Please ensure your have saved your program before using this command to renumber. **KNOWN BUG**: In release R43, due to improper parsing of escape tokens, REN will improperly treat arguments to these statements as line numbers: * `FRAME` * `RECT` * `MOUSE` * `COLOR` * `PSGWAV` This behavior has been fixed in R44. **EXAMPLE of REN Statement:** ```BASIC 10 PRINT "HELLO" 20 DATA 1,2,3 30 DATA 4,5,6 40 READ X 50 PRINT X 60 RESTORE 30 70 READ X 80 PRINT X 90 GOTO 10 REN 100,5 LIST 100 PRINT "HELLO" 105 DATA 1,2,3 110 DATA 4,5,6 115 READ X 120 PRINT X 125 RESTORE 110 130 READ X 135 PRINT X 140 GOTO 100 READY. ``` ### RESET **TYPE: Command** **FORMAT: RESET** **Action:** This command instructs the SMC to assert the reset line on the system, which performs a hard reset. This is equivalent to pressing the physical reset switch. **EXAMPLE of RESET Statement:** ```BASIC RESET ``` ### RESTORE **TYPE: Command** **FORMAT: RESTORE \[<linenum>\]** **Action:** This command resets the pointer for the `READ` command. Without arguments, it will reset the pointer to the first `DATA` constant in the program. With a parameter `linenum`, the command will reset the pointer to the first `DATA` constant at or after that line number. **EXAMPLE of RESTORE Statement:** ```BASIC 10 DATA 1,2,3 20 DATA 4,5,6 30 READ Y 40 PRINT Y 50 RESTORE 20 60 READ Y 70 PRINT Y ``` This program will output the number 1 followed by the number 4. ### RPT$ **TYPE: Function** **FORMAT: RPT$(<byte>,<count>)** **Action:** Returns a string of <count> instances of the PETSCII character represented by the numeric value <byte>. This function is similar in behavior to `CHR$()` but takes a second argument as a repeat count. `RPT$(A,1)` is functionally equivalent to `CHR$(A)`. **EXAMPLE of RPT$ function:** ```BASIC 10 REM TEN EXCLAMATION MARKS 20 PRINT RPT$(33,10) READY. RUN !!!!!!!!!! READY. ``` ### SAVE **TYPE: Command** **FORMAT: SAVE <filename> \[, <device>**\] **Action:** Saves a BASIC program to a file. This saves the currently loaded BASIC program to a file. If the device number is not supplied, SAVE will use the default drive. This is usually the SD card. Note that SAVE will not overwrite an existing file by default. To do this, you must prefix the filename with @:, like this: `SAVE "@:filename"` **EXAMPLES of SAVE:** ```BASIC SAVE "HELLO.PRG" ``` The above example saves your Hello World program to the SD card. ```BASIC SAVE "@:HELLO.PRG",9 ``` The above example overwrites an existing file on drive 9, which would be a Commodore style disk drive plugged into the IEC port. ### SCREEN **TYPE: Command** **FORMAT: SCREEN <mode>** **Action:** This command switches screen modes. For a list of supported modes, see [Chapter 3: Editor](X16%20Reference%20-%2003%20-%20Editor.md#chapter-3-editor). The value of -1 toggles between modes $00 and $03. **EXAMPLE of SCREEN Statement:** ```BASIC SCREEN 3 : REM SWITCH TO 40 CHARACTER MODE SCREEN 0 : REM SWITCH TO 80 CHARACTER MODE SCREEN -1 : REM SWITCH BETWEEN 40 and 80 CHARACTER MODE ``` ### SLEEP **TYPE: Command** **FORMAT: SLEEP \[<jiffies>\]** **Action:** With the default interrupt source configured and enabled, this command waits for `jiffies`+1 VSYNC events and then resumes program execution. In other words, `SLEEP` with no arguments is equivalent to `SLEEP 0`, which waits until the beginning of the next frame. Another useful example, `SLEEP 60`, pauses for approximately 1 second. Allowed values for `jiffies` is from 0 to 65535, inclusive. **EXAMPLE of SLEEP Statement:** ```BASIC 10 FOR I=1 TO 10 20 PRINT I 30 SLEEP 60 40 NEXT ``` ### SPRITE **TYPE: Command** **FORMAT: SPRITE <sprite idx>,<priority>\[,<palette offset>\[,<flip>\[,<x-width>\[,<y-width>\[,<color depth>\]\]\]\]\]** **Action:** This command configures a sprite's geometry, palette, and visibility. The first two arguments are required, but the remainder are optional. * `sprite idx` is a value between 0-127 inclusive. * `priority`, also known as z-depth changes the visibility of the sprite and above which layer it is rendered. Range is 0-3 inclusive. 0 = off, 1 = below layer 0, 2 = in between layers 0 and 1, 3 = above layer 1 * `palette offset` is the palette offset for the sprite. Range is 0-15 inclusive. This value is multiplied by 16 to determine the starting palette index. * `flip` controls the X and Y flipping of the sprite. Range is 0-3 inclusive. 0 = unflipped, 1 = X is flipped, 2 = Y is flipped, 3 = both X and Y are flipped. * `x-width` and `y-width` represent the dimensions of the sprite. Range is 0-3 inclusive. 0 = 8px, 1 = 16px, 2 = 32px, 3 = 64px. * `color depth` selects either 4 or 8-bit color depth for the sprite. 0 = 4-bit, 1 = 8-bit. This attribute can also be set by the `SPRMEM` command. Note: If VERA's sprite layer is disabled when the `SPRITE` command is called, the sprite layer will be enabled, regardless of the arguments to `SPRITE`. **EXAMPLE of SPRITE Statement:** ```BASIC 10 BVLOAD "MYSPRITE.BIN",8,1,$3000 20 SPRMEM 1,1,$3000,1 30 SPRITE 1,3,0,0,3,3 40 MOVSPR 1,320,200 ``` ### SPRMEM **TYPE: Command** **FORMAT: SPRMEM <sprite idx>,<VRAM bank>,<VRAM address>\[,<color depth>\]** **Action:** This command configures the address of where the sprite's pixel data is to be found. It also can change or set the color depth of the sprite. The first three arguments are required, but the last one is optional. * `sprite idx` is a value between 0-127 inclusive. * `VRAM bank` is a value, `0` or `1`, which represents which of the two 64k regions of VRAM to select. * `VRAM address` is a 16-bit value, \$0000-\$FFFF, is the address within the VRAM bank to point the sprite to. The lowest 5 bits are ignored. * `color depth` selects either 4 or 8-bit color depth for the sprite. 0 = 4-bit, 1 = 8-bit. This attribute can also be set by the `SPRITE` command. **EXAMPLE of SPRITE Statement:** ```BASIC 10 BVLOAD "MYSPRITE.BIN",8,1,$3000 20 SPRMEM 1,1,$3000,1 30 SPRITE 1,3,0,0,3,3 40 MOVSPR 1,320,200 ``` ### STRPTR **TYPE: Function** **FORMAT: STRPTR(<variable>)** **Action:** Returns the memory address of the first character of a string contained within a string variable. If the string variable has zero length, this function will likely still return a non-zero value pointing either to the close quotation mark in the literal assignment, or to somewhere undefined in string memory. Programs should check the `LEN()` of string variables before using the pointer returned from `STRPTR`. **EXAMPLE of STRPTR function:** ```BASIC 10 A$="MOO" 20 P=STRPTR(A$) 30 FOR I=0 TO LEN(A$)-1 40 PRINT CHR$(PEEK(P+I)); 50 NEXT 60 A$="" 70 P=STRPTR(A$) 80 FOR I=0 TO LEN(A$)-1 : REM THIS LOOP WILL STILL ALWAYS HAPPEN ONCE 90 PRINT CHR$(PEEK(P+I)); 100 NEXT RUN MOO" READY. ``` In this case, the pointer returned on line 70 pointed to the first character after the open quote on line 60. Since it was an empty string, the pointer ended up pointing to the close quote. To avoid this scenario, we should have checked the `LEN(A$)` before line 80 and skipped over the loop. ### SYS **TYPE: Command** **FORMAT: SYS <address>** **Action:** The SYS command executes a machine language subroutine located at <address>. Execution continues until an RTS is executed, and control returns to the BASIC program. In order to communicate with the routine, you can pre-load the CPU registers by using POKE to write to the following memory locations: * `$030C`: Accumulator * `$030D`: X Register * `$030E`: Y Register * `$030F`: Status Register/Flags When the routine is over, the CPU registers will be loaded back in to these locations. So you can read the results of a machine language routine by PEEKing these locations. **EXAMPLE of SYS statement:** Push a <CR> into the keyboard buffer. ```BASIC POKE $30C,13 SYS $FEC3 ``` Run the Machine Language Monitor (Supermon) ```BASIC SYS $FECC ``` ### TILE **TYPE: Command** **FORMAT: TILE <x>,<y>,<tile/screen code>\[,<attribute>\]** **Action:** The `TILE` command sets the tile or text character at the given x/y tile/character coordinate to the given screen code or tile index, optionally resetting the attribute byte. It works for tiles or text on Layer 1. In the default text mode, this can be used to quickly change a character on the screen and optionally its fg/bg color without needing to calculate the VRAM address for VPOKE. However, it can also be used if VERA Layer 1's map base value is changed or the map size is changed. **EXAMPLE of TILE command:** ```BASIC 10 REM VERY SLOWLY CLEAR THE SCREEN IN STYLE 20 FOR Y=59 TO 0 STEP -1 30 FOR X=79 TO 0 STEP -1 40 FOR I=255 TO 32 STEP -1 50 TILE X,Y,I 60 NEXT:NEXT:NEXT ``` ### TATTR **TYPE: Function** **FORMAT: TATTR(<x coordinate>,<y coordinate>)** **Action:** The `TATTR`function retrieves the text/tile attribute at the given x/y coordinate. It works for tiles or text on Layer 1. In the default text modes, this can be used to retrieve the color attribute (fg/bg) of a specific coordinate without needing to calculate the VRAM address for VPEEK. **EXAMPLE of TATTR command:** ```BASIC 10 REM COPY BUTTERFLY LOGO WITH COLORS TO CENTER OF 80X60 SCREEN 20 XO = 37 : YO = 27 30 FOR X = 0 TO 6 40 FOR Y = 0 TO 6 50 TD = TDATA(X, Y) 60 TA = TATTR(X, Y) 70 TILE XO+X, YO+Y, TD, TA 80 NEXT:NEXT ``` ### TDATA **TYPE: Function** **FORMAT: TDATA(<x coordinate>,<y coordinate>)** **Action:** The `TDATA`function retrieves the text/tile at the given x/y coordinate. It works for tiles or text on Layer 1. In the default text modes, this can be used to retrieve the character a specific coordinate without needing to calculate the VRAM address for VPEEK. **EXAMPLE of TATTR command:** ```BASIC 10 REM COPY BUTTERFLY LOGO TO CENTER OF 80X60 SCREEN 20 XO = 37 : YO = 27 30 FOR X = 0 TO 6 40 FOR Y = 0 TO 6 50 TD = TDATA(X, Y) 60 TILE XO+X, YO+Y, TD 70 NEXT:NEXT ``` ### VPEEK **TYPE: Integer Function** **FORMAT: VPEEK (<bank>, <address>)** **Action:** Return a byte from the video address space. The video address space has 17 bit addresses, which is exposed as 2 banks of 65536 addresses each. In addition, VPEEK can reach add-on VERA cards with higher bank numbers. BANK 2-3 is for IO3 (VERA at \$9F60-\$9F7F) BANK 4-5 is for IO4 (VERA at \$9F80-\$9F9F) **EXAMPLE of VPEEK Function:** ```BASIC PRINT VPEEK(1,$B000) : REM SCREEN CODE OF CHARACTER AT 0/0 ON SCREEN ``` ### VPOKE **TYPE: Command** **FORMAT: VPOKE <bank>, <address>, <value>** **Action:** Set a byte in the video address space. The video address space has 17 bit addresses, which is exposed as 2 banks of 65536 addresses each. In addition, VPOKE can reach add-on VERA cards with higher bank numbers. BANK 2-3 is for IO3 (VERA at \$9F60-\$9F7F) BANK 4-5 is for IO4 (VERA at \$9F80-\$9F9F) **EXAMPLE of VPOKE Statement:** ```BASIC VPOKE 1,$B000+1,1 * 16 + 2 : REM SETS THE COLORS OF THE CHARACTER REM AT 0/0 TO RED ON WHITE ``` ### VLOAD **TYPE: Command** **FORMAT: VLOAD <filename>, <device>, <VERA_high_address>, <VERA_low_address>** **Action:** Loads a file directly into VERA RAM, skipping the two-byte header that is presumed to be in the file. **EXAMPLES of VLOAD:** ```BASIC VLOAD "MYFILE.PRG", 8, 0, $4000 :REM LOADS MYFILE.PRG FROM DEVICE 8 TO VRAM $4000 REM WHILE SKIPPING THE FIRST TWO BYTES OF THE FILE. ``` To load a raw binary file without skipping the first two bytes, use [`BVLOAD`](#bvload) ## Other New Features ### Hexadecimal and Binary Literals The numeric constants parser supports both hex (`$`) and binary (`%`) literals, like this: ```BASIC PRINT $EA31 + %1010 ``` The size of hex and binary values is only restricted by the range that can be represented by BASIC's internal floating point representation. ### LOAD into VRAM In BASIC, the contents of files can be directly loaded into VRAM with the `LOAD` statement. When a secondary address greater than one is used, the KERNAL will now load the file into the VERA's VRAM address space. The first two bytes of the file are used as lower 16 bits of the address. The upper 4 bits are `(SA-2) & 0x0ff` where `SA` is the secondary address. Examples: ```BASIC 10 REM LOAD VERA SETTINGS 20 LOAD"VERA.BIN",1,17 : REM SET ADDRESS TO $FXXXX 30 REM LOAD TILES 40 LOAD"TILES.BIN",1,3 : REM SET ADDRESS TO $1XXXX 50 REM LOAD MAP 60 LOAD"MAP.BIN",1,2 : REM SET ADDRESS TO $0XXXX ``` ### Default Device Numbers In BASIC, the LOAD, SAVE and OPEN statements default to the last-used IEEE device (device numbers 8 and above), or 8. ## Internal Representation Like on the C64, BASIC keywords are tokenized. * The C64 BASIC V2 keywords occupy the range of \$80 (`END`) to \$CB (`GO`). * BASIC V3.5 also used \$CE (`RGR`) to \$FD (`WHILE`). * BASIC V7 introduced the \$CE escape code for function tokens \$CE-\$02 (`POT`) to \$CE-\$0A (`POINTER`), and the \$FE escape code for statement tokens \$FE-\$02 (`BANK`) to \$FE-\$38 (`SLOW`). * The unreleased BASIC V10 extended the escaped tokens up to \$CE-\$0D (`RPALETTE`) and \$FE-\$45 (`EDIT`). The X16 BASIC aims to be as compatible as possible with this encoding. Keywords added to X16 BASIC that also exist in other versions of BASIC match the token, and new keywords are encoded in the ranges \$CE-\$80+ and \$FE-\$80+. ## Auto-Boot When BASIC starts, it automatically executes the `BOOT` command, which tries to load a PRG file named `AUTOBOOT.X16` from device 8 and, if successful, runs it. Here are some use cases for this: * An SD card with a game can auto-boot this way. * An SD card with a collection of applications can show a menu that allows selecting an application to load. * The user's "work" SD card can contain a small auto-boot BASIC program that sets the keyboard layout and changes the screen colors, for example.